package org.infoset.xml.util;

import java.net.*;
import java.util.*;
import java.util.logging.*;
import org.infoset.xml.*;

public class ItemProperties {

   public static URI findBaseURI(Item node) {
      if (node==null) {
         return null;
      }
      if (node instanceof Parent) {
         return ((Parent)node).getBaseURI();
      } else {
         Parent origin = node.getOrigin();
         return origin!=null ? origin.getBaseURI() : null;
      }
   }
   
   public static Item copyOf(ItemConstructor iconst,Item i) 
      throws XMLException
   {
      return copyOf(iconst,i,true,null);
   }
   
   public static Item copyOf(ItemConstructor iconst,Item i,boolean deep) 
      throws XMLException
   {
      return copyOf(iconst,i,deep,null);
   }
           
   public static Item copyOf(ItemConstructor iconst,Item i,boolean deep,URI baseURI) 
      throws XMLException
   {
      switch (i.getType()) {
         case ElementItem:
         {
            Element e = (Element)i;
            Element ne = iconst.createElement(e.getName());
            ne.setBaseURI(baseURI!=null ? baseURI : e.getBaseURI());
            ne.setPrefix(e.getPrefix());
            copyNamespaceDeclarations(e,ne);
            if (deep) {
               for (Attribute a : e.getAttributes().values()) {
                  ne.setAttributeValue(a.getName(),a.getText());
               }
            }
            return ne;
         }
         case ElementEndItem:
            return iconst.createElementEnd(((ElementEnd)i).getName());
         case DocumentItem:
            return iconst.createDocument(baseURI!=null ? baseURI : ((Document)i).getBaseURI());
         case DocumentEndItem:
            return iconst.createDocumentEnd();
         case CharactersItem:
            return iconst.createCharacters(((Characters)i).getText());
         case ProcessingInstructionItem:
         {
            ProcessingInstruction pi = (ProcessingInstruction)i;
            return iconst.createProcessingInstruction(pi.getName(),pi.getText());
         }
         case CommentItem:
            return iconst.createComment(((Comment)i).getText());
      }
      
      // The rest can't be duplicated
      return null;
   }
   
   public static void copyNamespaceDeclarations(Element from, Element to) {
      if (from.hasNamespaceDeclarations()) {
         Map<String,URI> p = from.getNamespaceScope().getDataProxy();
         for (String prefix : p.keySet()) {
            to.addNamespaceBinding(prefix,p.get(prefix));
            //Logger.getAnonymousLogger().info("Copied namespace decl "+prefix+" -> "+p.getNamespace(prefix));
         }
      }
   }

   public static Item copyOfSubtree(ItemConstructor iconst,Item i) 
      throws XMLException
   {
      return copyOfSubtree(iconst,i,null);
   }
      
   public static Item copyOfSubtree(ItemConstructor iconst,Item i,URI baseURI) 
      throws XMLException
   {
      
      switch (i.getType()) {
         case ElementItem:
         {
            Element e = (Element)copyOf(iconst,i,true,baseURI);
            copyChildren(iconst,(Parent)i,e,baseURI);
            return e;
         }
         case DocumentItem: {
            Document doc = (Document)copyOf(iconst,i,true,baseURI);
            copyChildren(iconst,(Parent)i,doc,baseURI);
            return doc;
         }
         default:
            return copyOf(iconst,i);
      }
      
   }
   
   public static void copyChildren(ItemConstructor iconst,Parent from,Parent to) 
      throws XMLException
   {
      copyChildren(iconst,from,to,null);
   }
   public static void copyChildren(ItemConstructor iconst,Parent from,Parent to,URI baseURI) 
      throws XMLException
   {
      for (Iterator<Child> children=from.iterator(); children.hasNext();) {
         Child c = children.next();
         Child newChild = (Child)copyOfSubtree(iconst,c,baseURI);
         to.add(newChild);
      }
   }
}

